package com.ficus.road.maintain.task;

import com.ficus.road.maintain.core.model.GpsLocation;
import com.ficus.road.maintain.core.model.smartnew.SmartRoadGps;
import com.ficus.road.maintain.core.model.smartnew.SmartRoadSection;
import com.ficus.road.maintain.dao.smartnew.*;
import com.ficus.road.maintain.service.HitService;
import com.ficus.road.maintain.service.smartnew.*;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author xiawen yang
 * @date 2022/3/1 下午1:56
 */
@Data
@Component
@RequiredArgsConstructor
@Slf4j
public class SmartDecisionTask {

    private static Map<String, String> idNameMap = new ConcurrentHashMap<>();
    //    private static Map<Coordinate, String> gpsIdMap = new ConcurrentHashMap<>();
    private final HitService hitService;
    private final SmartScreeningService smartScreeningService;
    private final SmartRoadSectionService smartRoadSectionService;
    private final SmartRankTableService smartRankTableService;
    private final SmartProjectService smartProjectService;
    private final SmartDailyMaintenanceDao smartDailyMaintenanceDao;
    private final SmartReserveLibraryDao smartReserveLibraryDao;
    private final SmartDecisionDao smartDecisionDao;
    private final SmartRoadGpsTestService smartRoadGpsTestService;
    private final SmartRoadGpsService smartRoadGpsService;
    private final SmartRoadSectionDao smartRoadSectionDao;
    private final SmartHighwayDao smartHighwayDao;
    private final SmartTableMergedDao smartTableMergedDao;
    private final SmartTableVerticalDao smartTableVerticalDao;
    private final SmartValuationMergedDao smartValuationMergedDao;

    @PostConstruct
    public void init() {
        idNameMap = smartRoadSectionService.findAllSection().stream().collect(Collectors.toMap(SmartRoadSection::getId, SmartRoadSection::getRoadName));
//        smartRoadGpsTestService.findAll().forEach(gps -> {
//            gps.getCoordinates().forEach(coordinate -> {
//                gpsIdMap.put(coordinate, gps.getId());
//            });
//        });
        // 项目初筛
//        highwayScreeningStatistic();
//        // 智能检测
//        highwayInspectionStatistic();
//        // 智能排序
//        highwaySortStatistic();
//        // 智能估价
//        highwayValuationStatistic();
    }

    //    @Scheduled(cron = "0 25 21 * * ?", zone = "GMT+8:00")
    public void refreshSmartRoadOfHit() {
//        Map<String, SmartRoadSection> collect = smartRoadSectionService.findAllSection().stream().collect(Collectors.toMap(SmartRoadSection::getId, Function.identity()));
//        Date endDate = new Date();
//        Date startDate = DateUtils.addDays(new Date(), -30);
//        List<Hit> hits = new ArrayList<>();
//        ArrayList<Object> list = new ArrayList<>();
//        AtomicInteger zero = new AtomicInteger(0);
//        AtomicInteger one = new AtomicInteger(0);
//        AtomicInteger two = new AtomicInteger(0);
//        AtomicInteger three = new AtomicInteger(0);
//        AtomicInteger more = new AtomicInteger(0);
//        AtomicInteger distance = new AtomicInteger(0);
//        AtomicInteger noDistance = new AtomicInteger(0);
//        AtomicInteger hitSize = new AtomicInteger(0);
//        for (int i = 1; i <= 12; i++) {
//            System.out.println("开始时间: " + MyDateUtil.dateFormatStr(startDate, "yyyy-MM-dd"));
//            System.out.println("结束时间: " + MyDateUtil.dateFormatStr(endDate, "yyyy-MM-dd"));
//            Query query = new Query();
//            query.addCriteria(Criteria.where("first_hit_time").gte(startDate.getTime() / 1000).lte(endDate.getTime() / 1000));
//            hits = hitService.findForSmartRoad(query);
//            hitSize.getAndAdd(hits.size());
//            hits.forEach(hit -> {
//                System.out.println("---------------");
//                // 判断该病害属于smart_road_section中的哪个路段
//                GpsLocation gpsLocation = hit.getAttrs().getGpsLocation();
//                List<SmartRoadGps> gpsList = smartRoadGpsService.geoSearch(gpsLocation);
//                Map<String, List<SmartRoadGps>> idGpsMap = gpsList.stream().collect(Collectors.groupingBy(SmartRoadGps::getSecId));
//                if (idGpsMap.size() == 0) {
//                    System.out.println("路名: " + hit.getAttrs().getRoadName() + "不在已知路段上！");
//                    list.add(hit.getAttrs().getRoadName());
//                    zero.getAndIncrement();
//                } else if (idGpsMap.size() == 1) {
//                    System.out.println("定位到一条路段");
//                    String secId = idGpsMap.keySet().toArray(new String[0])[0];
//                    SmartRoadSection sec = collect.get(secId);
//                    hit.getAttrs().setSmartRoadSecId(secId);
//                    hit.getAttrs().setSmartRoasSecType(sec.getRoadType());
//                    hitService.saveOrUpdate(hit);
//                    one.getAndIncrement();
//                } else if (idGpsMap.size() == 2) {
//                    System.out.println("定位到两条路段！！！");
//                    String targetId = null;
//                    boolean flag = true;
//                    int mapSize = 0;
//                    Iterator<String> iterator = idGpsMap.keySet().iterator();
//                    while (iterator.hasNext()) {
//                        String id = iterator.next();
//                        int size = idGpsMap.get(id).size();
//                        if (size > mapSize) {
//                            mapSize = size;
//                            targetId = id;
//                        }
//                        if (size == 2) {
//                            flag &= true;
//                        } else {
//                            flag &= false;
//                        }
//                    }
//                    if (flag) {
//                        // 计算距离
//                        System.out.println("计算距离中..........");
//                        targetId = locating(gpsLocation, idGpsMap);
//                        SmartRoadSection sec = collect.get(targetId);
//                        hit.getAttrs().setSmartRoadSecId(targetId);
//                        hit.getAttrs().setSmartRoasSecType(sec.getRoadType());
//                        hitService.saveOrUpdate(hit);
//                        distance.getAndIncrement();
//                    } else {
//                        SmartRoadSection sec = collect.get(targetId);
//                        hit.getAttrs().setSmartRoadSecId(targetId);
//                        hit.getAttrs().setSmartRoasSecType(sec.getRoadType());
//                        hitService.saveOrUpdate(hit);
//                        noDistance.getAndIncrement();
//                    }
//                    two.getAndIncrement();
//                } else if (idGpsMap.size() == 3) {
//                    System.out.println("定位到三条路段");
//                    three.getAndIncrement();
//                } else {
//                    System.out.println("定位到三条以上路段");
//                    more.getAndIncrement();
//                }
//            });
//            startDate = DateUtils.addDays(startDate, -30);
//            endDate = DateUtils.addDays(endDate, -30);
//        }
//        System.out.println("总病害数: " + hits.size());
//        System.out.println("不在已知路段的病害数: " + zero.get());
//        System.out.println("定位到一条路段的病害数: " + one.get());
//        System.out.println("需要计算距离的病害数： " + distance.get());
//        System.out.println("不需要计算距离的病害数： " + noDistance.get());
//        System.out.println("定位到两条路段的病害数: " + two.get());
//        System.out.println("定位到三条路段的病害数: " + three.get());
//        System.out.println("定位到三条以上路段的病害数: " + more.get());
////        System.out.println("不在已知路段的病害所在道路名: " + list);
    }

    private String locating(GpsLocation target, Map<String, List<SmartRoadGps>> map) {
        Iterator<String> iterator = map.keySet().iterator();
        double min = Double.MAX_VALUE;
        String result = null;
        while (iterator.hasNext()) {
            String secId = iterator.next();
            List<SmartRoadGps> gpsList = map.get(secId);
            GpsLocation l1 = GpsLocation.builder().longitude(gpsList.get(0).getLocation().get(0)).latitude(gpsList.get(0).getLocation().get(1)).build();
            GpsLocation l2 = GpsLocation.builder().longitude(gpsList.get(1).getLocation().get(0)).latitude(gpsList.get(1).getLocation().get(1)).build();
            GpsLocation foot = getFoot(l1, l2, target);
            Double distance = calculateDistance(target, foot);
            if (distance < min) {
                min = distance;
                result = secId;
            }
        }
        return result;
    }

    /**
     * 计算l3在l1和l2上的垂足的坐标
     *
     * @param l1
     * @param l2
     * @param l3
     * @return
     */
    private GpsLocation getFoot(GpsLocation l1, GpsLocation l2, GpsLocation l3) {
        GpsLocation foot = new GpsLocation();
        double dx = l1.getLongitude() - l2.getLongitude();
        double dy = l1.getLatitude() - l2.getLatitude();
        double u = (l3.getLongitude() - l1.getLongitude()) * dx + (l3.getLatitude() - l1.getLatitude()) * dy;
        u /= dx * dx + dy * dy;
        foot.setLongitude(l1.getLongitude() + u * dx);
        foot.setLatitude(l1.getLatitude() + u * dy);
        return foot;
    }

    private Double calculateDistance(GpsLocation l1, GpsLocation l2) {
        GlobalCoordinates g1 = new GlobalCoordinates(l1.getLatitude(), l1.getLongitude());
        GlobalCoordinates g2 = new GlobalCoordinates(l2.getLatitude(), l2.getLongitude());
        GeodeticCurve curve = new GeodeticCalculator().calculateGeodeticCurve(Ellipsoid.WGS84, g1, g2);
        return curve.getEllipsoidalDistance();
    }
}
